<template>
  <el-row>
    <div class="block">
      <el-date-picker v-model="value2" type="datetimerange" :shortcuts="shortcuts" range-separator="To" start-placeholder="起始日期" end-placeholder="结束日期"/>
    </div>
    <div class="block">
      <el-select v-model="value3" placeholder="选择区域" style="width: 240px">
        <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
      </el-select>
    </div>
    <div class="block">
      <el-radio-group v-model="timeView" @change="updateView">
        <el-radio :label="1" :class="{ active: timeView === 1 }" border>按件</el-radio>
        <el-radio :label="2" :class="{ active: timeView === 2 }" border>按小时</el-radio>
        <el-radio :label="3" :class="{ active: timeView === 3 }" border>按天</el-radio>
      </el-radio-group>
    </div>

  </el-row>
  <div>
    <el-card><div ref="chart" style="height: 370px; width: 1300px"></div></el-card>
    <el-card>
      <div ref="chart2" style="height: 300px; width: 1300px"></div>
    </el-card>
    <table class="summary-table">
      <thead>
        <tr>
          <th>总工位数</th>
          <th>超上限工位数</th>
          <th>超下限工位数</th>
          <th>符合工位数</th>
          <th>工位符合率</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>{{ totalStations }}</td>
          <td>{{ overUpperLimitStations }}</td>
          <td>{{ overLowerLimitStations }}</td>
          <td>{{ conformingStations }}</td>
          <td>{{ stationConformityRate }}%</td>
        </tr>
      </tbody>
    </table>
    <el-card>
      <el-button @click="exportToExcel">导出为 Excel</el-button>
      <el-table :data="pagedTableData1" border style="width: 90%">
    <el-table-column prop="时间" label="时间" width="450"></el-table-column>
    <el-table-column prop="节拍" label="节拍" width="450"></el-table-column>
    <el-table-column prop="工位" label="工位" width="450"></el-table-column>
  </el-table>
  <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="currentPage"
        :page-sizes="[5, 10, 30, 50]"
        :page-size="pageSize"
        layout="total, sizes, prev, pager, next, jumper"
        :total="totalItems"
      />
    </el-card>
    <el-button @click="toggleCardVisibility">
    {{ isCardVisible ? '' : '' }}
  </el-button>
  <el-card v-show="isCardVisible">
    <el-button @click="resetTableData">重置补偿</el-button>
    <el-table :data="tableData" border style="width: 90%">
      <el-table-column prop="point_id" label="工位" width="250" />
      <el-table-column prop="actual_cycle" label="实际节拍" width="250" />
      <el-table-column prop="target_cycle" label="节拍目标" width="250" />
      <el-table-column prop="compensation" label="补偿节拍" width="250">
        <template #default="{ row }">
          <el-input
            v-model.number="row.compensation"
            size="small"
            @change="applyCompensation(row)"
          />
        </template>
      </el-table-column>
      <el-table-column prop="accumulated_compensation" label="累计补偿节拍" width="250" />
    </el-table>
  </el-card>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, watch, toRef, toRefs,computed, onBeforeUnmount } from "vue";
import * as echarts from "echarts"; //引入echarts核心模块
import axios from "axios"; //引入echarts核心模块
import { useRouter } from "vue-router";
import XLSX from 'xlsx'; // 导入 xlsx
import { saveAs } from 'file-saver';


let lastPointId = null;
const value2 = ref([]);
const isCardVisible = ref(false);

const toggleCardVisibility = () => {
  isCardVisible.value = !isCardVisible.value;
};
const shortcuts = [
  {
    text: "近1周",
    value: () => {
      const end = new Date();
      const start = new Date();
      start.setDate(start.getDate() - 7);
      return [start, end];
    },
  },
  {
    text: "近2周",
    value: () => {
      const end = new Date();
      const start = new Date();
      start.setDate(start.getDate() - 14);
      return [start, end];
    },
  },
  {
    text: "近1月",
    value: () => {
      const end = new Date();
      const start = new Date();
      start.setMonth(start.getMonth() - 1);
      return [start, end];
    },
  },
];
const chart = ref(); 
const chart2 = ref();
const chartInstance2 = ref(null);
const series_data = ref();
const series_data1 = ref();
const timeView = ref(1); 
const tableData1 = ref([]);
const currentPage = ref(1);
const pageSize = ref(5);
const totalItems = ref(0);
const averagedData = ref([]);
const compensationValues = ref(new Map());
const excludedPoints = [
  '2475','2185','1196','3060','2420','2355','3120','1008','1053','2140','2410','2430','3020','3070','3080','3090','109A','3061','3063','1115','1075','121A','1195','2145','4010','3062','4020','LG01','4050','1150','5010','5020','303A','1126','2330','213A','1200','1140','1245','1420','1235','1165','2155','2055','5040','2225','3105','1035','1355','1368','1315','1405','1265','1070','143A'
];
const excludedPointsauto = [
  '1010','1050','1060','1090','1100','1170','1180','1220','1230','1250','1261','1260','1280','1300','1330','1340','1360','1380','1390','1410','1430','4010','4050',
  '2010','2020','2030','2060','2070','2170','2185','2190','2230','2240','2250','2255','2280','2290','2300','2310','2340','2360','2390','2400','2410','2430','2460','2480','2490','5010','5020',
  '3010','305A','3120','1053'
];
const excludedPointsmanual = [
  '1020','1030','1055','1080','1110','1120','1160','1190','121A','121C','1240','1275','1270','1290','1310','1320','135A','135B','1370','140A','140B','4020',
  '205A','205B','2080','2090','2110','213B','2160','2180','2210','2220','2320','2350','2370','2470',
 ,'3020','303A','303B','3040','3080','3090','3100','3110','1058'
];

const handleSizeChange = (val: number) => {
  pageSize.value = val;
  updatePagedData();
};
const handleCurrentChange = (val: number) => {
  currentPage.value = val;
  updatePagedData();
};

const updatePagedData = () => {
  const startIndex = (currentPage.value - 1) * pageSize.value;
  const endIndex = startIndex + pageSize.value;
  pagedTableData1.value = tableData1.value.slice(startIndex, endIndex);
};

const pagedTableData1 = ref([]);

const loadTableData = () => {
  const storageKey = `tableData_${value3.value}`;
  const savedData = localStorage.getItem(storageKey);
  if (savedData) {
    let parsedSavedData = JSON.parse(savedData);
    tableData.value = parsedSavedData.map(item => ({
      ...item,
      actual_cycle: item.field_val + (item.accumulated_compensation || 0),
    }));
  }
};

const saveTableData = () => {
  const storageKey = `tableData_${value3.value}`;
  localStorage.setItem(storageKey, JSON.stringify(tableData.value));
};

const initChart = async () => {
  if (chart.value == null) {
    return;
  }

  echarts.dispose(chart.value);
  var myChart = echarts.init(chart.value);
  myChart.setOption({});
  let option = {
    tooltip: {
  trigger: "axis",
  formatter: function (params) {
    var result = "";
    const pointId = params[0].name;
    const seriesInfo = {};

    for (var i = 0; i < params.length; i++) {
      var param = params[i];

      if (param.name === pointId) {
        const seriesName = param.seriesName;
        const value = param.value;
        if (!seriesInfo[seriesName]) {
          seriesInfo[seriesName] = value;
        }
      }
    }
    result += pointId + "<br/>";
    for (const [seriesName, value] of Object.entries(seriesInfo)) {
      result += seriesName + ": " + value + "<br/>";
    }
    const maxVal = maxFieldValMap.get(pointId)/10;
    const minVal = minFieldValMap.get(pointId)/10;
    const over = overTargetCountMap.get(pointId);
    const overCT = overCTCountMap.get(pointId);
    const lessCT = lessCTCountMap.get(pointId);
    const conformityRate = conformityRateMap.get(pointId);
    result += "最大节拍: " + maxVal + "<br/>";
    result += "最小节拍: " + minVal + "<br/>";
    result += "超节拍次数：" + over + "<br/>";
    result += "超+5%CT数：" + overCT + "<br/>";
    result += "超-5%CT数：" + lessCT + "<br/>";
    result += "节拍符合率: " + (conformityRate * 100).toFixed(2) + "%<br/>";

    return result;
  },
},
    legend: {
      data: ["节拍","目标节拍","目标上限","目标下限","FTQ"],
      orient: "horizontal", // 改为水平显示
      left: "left", // 将图例放置在左侧
      top: "top", // 将图例放置在顶部
      itemGap: 10, // 图例项之间的间距
    },
    toolbox: {
      show: true,
      feature: {
        mark: { show: true },
        dataView: { show: true, readOnly: false },
        magicType: { show: true, type: ["line", "bar"] },
        restore: { show: true },
        saveAsImage: { show: true },
      },
    },
    title: {
      text: `${value3Label.value} 整线节拍统计`,
      left: "center",
      subtext: "s",
      textStyle: {
        color: "black", 
      },
      subtextStyle: {
        fontWeight: "bold",
      },
    },
    xAxis: {
      type: "category",
      data: series_data1.value,
      axisLabel: {
            rotate: 70 
          }
    },
    yAxis: [
          {
            type: 'value',
            name: '节拍',
            position: 'left',
            axisLabel: {
              formatter: '{value}'
            }
          },
          {
            type: 'value',
            name: 'Rate (%)',
            position: 'right',
            axisLabel: {
              formatter: '{value} %'
            },
            max: 100,
          }
        ],
    series: [
    {
        name: "节拍",
        type: "bar",
        stack: 'total',
        data: [],
        yAxisIndex: 0,
        itemStyle: {
          normal: {
            color: function(params) {
              const pointId = series_data1.value[params.dataIndex];
              const actualCycle = tableData.value.find(item => item.point_id === pointId)?.actual_cycle || 0;
              const targetCycle = targetCycleMap.get(pointId) || 0;
              if (actualCycle > targetCycle * 1.05) {
                return 'red'; 
              } else if (actualCycle < targetCycle * 0.95) {
                return 'orange'; 
              } else {
                return '#00ff00'; 
              }
            }
          }
        },
      },
      {
        name: "目标节拍",
        type: "line",
        step: "start",
        yAxisIndex: 0,
        symbol: 'circle', 
        data: targetSeriesData.value, 
        color: '#00ff00', 
        lineStyle: {
        color: '#00ff00', 
        width: 1.4,
        type:'dashed',
        },
      },
      {
        name: "目标上限",
        type: "line",
        step: "start",
        yAxisIndex: 0,
        symbol: 'circle', 
        data: maxTargetSeriesData.value, 
        color: 'red', 
        lineStyle: {
        color: 'red', 
        width: 1.4,
        type:'dashed',
        },
      },
      {
        name: "目标下限",
        type: "line",
        step: "start",
        yAxisIndex: 0,
        symbol: 'circle', 
        data: minTargetSeriesData.value, 
        color: 'orange', 
        lineStyle: {
        color: 'orange', 
        width: 1.4,
        type:'dashed',
        },
      },
      {
        name: "FTQ",
        type: "line",
        data: [], 
        symbol: 'circle',
        yAxisIndex: 1,
        color: '#b6a2de', 
        lineStyle: {
          color: '#b6a2de',
          width: 1.4,
          type: 'solid'
        },
      },
    ],
  };
  const actualCycleData = series_data1.value.map(pointId => {
    const row = tableData.value.find(item => item.point_id === pointId);
    return row ? row.actual_cycle : null;
  });

  option.series.find(s => s.name === "节拍").data = actualCycleData;
  const ftqRateData = [];
series_data1.value.forEach(pointId => {
  let ftqRate = 0;
  let longestMatchLength = 0;

  for (const [station, rate] of ftqRateMap) {
    if (pointId.includes(station) && station.length > longestMatchLength) {
      ftqRate = rate;
      longestMatchLength = station.length;
    }
  }
  if (ftqRate > 0) {
    ftqRateData.push(ftqRate * 100); 
  } else {

    ftqRateData.push(null);
  }
});

option.series.find(s => s.name === "FTQ").data = ftqRateData;
  myChart.on('click', (params) => {
    console.log('Clicked:', params);
    const point_id = params.name; 
    useShowDataInHtmlForTable(point_id);
  });
  myChart.setOption(option);
};
const initChart2 = (seriesData, point_id, targetCycle) => {
  if (chartInstance2.value == null) {
    return;
  }

  echarts.dispose(chartInstance2.value);
  var myChart2 = echarts.init(chartInstance2.value);
  myChart2.setOption({});

  let option = {
    title: {
      text: `${point_id} 节拍统计`,
      left: "center",
      subtext: "s",
      textStyle: {
        color: "black", 
      },
      subtextStyle: {
        fontWeight: "bold",
      },
    },
    legend: {
      data: ["节拍","目标节拍","目标上限","目标下限"],
      orient: "horizontal", // 改为水平显示
      left: "left", // 将图例放置在左侧
      top: "top", // 将图例放置在顶部
      itemGap: 10, // 图例项之间的间距
    },
    tooltip: {
      trigger: 'axis', // 设置触发方式为基于轴
      axisPointer: { // 坐标轴指示器，坐标轴触发有效
        type: 'shadow' // 默认为直线，可选为：'line' | 'shadow'
      },
      formatter: function (params) {
        const barParam = params.filter(param => param.seriesType === 'bar')[0];
        const lineParam = params.filter(param => param.seriesType === 'line')[0];
        if (barParam && lineParam) {
          const targetCycle = lineParam.value;
          const value = barParam.value;
          const targetUpperLimit = parseFloat((targetCycle * 1.05).toFixed(2));
          const targetLowerLimit = parseFloat((targetCycle * 0.95).toFixed(2));
          return `
            <span style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:#59c4e6;"></span>
            时间: ${barParam.name}<br/>
            节拍: ${value}<br/>
            目标节拍: ${targetCycle}<br/>
            目标上限: ${targetUpperLimit}<br/>
            目标下限: ${targetLowerLimit}
          `;
        }
        return '';
      }
    },
    xAxis: {
      type: "category",
      data: seriesData.map(item => item.name),
    },
    dataZoom: [
      {
        type: "slider",
        start: 0,
        end: 100,
      },
      {
        type: "inside",
        start: 90,
        end: 100,
      },
    ],
    yAxis: {
      type: "value",
    },
    series: [
    {
        name: "节拍",
        type: "bar",
        data: seriesData.map(item => {
          const value = item.value;
          const color = value > targetCycle * 1.05 ? 'red' :
                        value < targetCycle * 0.95 ? 'orange' : '#00ff00';
          return {
            value: value,
            itemStyle: {
              color: color
            }
          };
        }),
      },
      {
        name: "目标节拍",
        type: "line",
        data: Array(seriesData.length).fill(targetCycle), 
        symbol: 'circle',
        color:'#00FF00',
        lineStyle: {
          color: '#00ff00',
          width: 1.4,
          type: 'dashed'
        }
      },
      {
        name: "目标上限",
        type: "line",
        data: Array(seriesData.length).fill(targetCycle * 1.05),
        symbol: 'circle',
        color:'red',
        lineStyle: {
          color: 'red',
          width: 1.4,
          type: 'dashed'
        }
      },
      {
        name: "目标下限",
        type: "line",
        data: Array(seriesData.length).fill(targetCycle*0.95),
        symbol: 'circle',
        color:'orange',
        lineStyle: {
          color: 'orange',
          width: 1.4,
          type: 'dashed'
        }
      },
    ],
  };

  myChart2.setOption(option);
};
onMounted(() => {
  const todayStart = new Date();
  todayStart.setHours(8, 0, 0, 0); 
  const todayEnd = new Date(); 
  value2.value = [todayStart, todayEnd];
  loadTableData();
  use_show_data_in_html2();

  chartInstance2.value = chart2.value;
  updatePagedData(); 
});

onBeforeUnmount(() => {
  saveTableData();
});

const value3 = ref("PTA00000001ASOP");
const value3Label = ref("装配手动站");
const router = useRouter();
const options = [
  { value: "MPTA0000001ASOP", label: "装配自动站" },
  { value: "PTA00000001ASOP", label: "装配手动站" },
  { value: "MPTASCAS011ASOP", label: "装配A" },
  { value: "MPTAHCAH011ASOP", label: "装配B" },
  { value: "MPTACCAC011ASOP", label: "装配C" },
  { value: "MPTBKCBK012CBM1", label: "缸体M1设备" },
  { value: "MPTBKCBK022CBM2", label: "缸体M2设备" },
  { value: "MPTHDCHD013CHM1", label: "缸盖M1设备" },
  { value: "MPTHDCHD023CHM2", label: "缸盖M2设备" },
  { value: "MPTCKCCK014CSOP", label: "曲轴M1设备" },
];

watch(value3, (newValue) => {
  const selectedOption = options.find(option => option.value === newValue);
  if (selectedOption) {
    value3Label.value = selectedOption.label;
  }
});

function formatDate(d: string) {
  var date = new Date(d);
  var YY = date.getFullYear() + "-";
  var MM = (date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1) + "-";
  var DD = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
  var hh = (date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":";
  var mm = (date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()) + ":";
  var ss = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
  return YY + MM + DD + " " + hh + mm + ss;
}

var construct_url = "";
watch([value2, value3], () => {
  loadTableData();
  const start_time = formatDate(value2.value[0]);
  const end_time = formatDate(value2.value[1]);
  let newvalue3;
  let apiEndpoint;

  if (value3.value.startsWith('MPTA0000001')) {
    newvalue3 = value3.value.substring(0, 4); 
    apiEndpoint = "man_ana_sql_server/get_AS_LastCt_filter";
  }
  else if (value3.value.startsWith('PTA00000001')) {
    newvalue3 = value3.value.substring(0, 3);
    apiEndpoint = "man_ana_sql_server/get_AS_LastCt_filter";
  }
  else if (value3.value.startsWith('MPTASCAS011') || value3.value.startsWith('MPTAHCAH011') ||
      value3.value.startsWith('MPTACCAC011')){
    newvalue3 = value3.value.substring(0, 10);
    apiEndpoint = "man_ana_sql_server/get_AS_LastCt_filter";
  } else {
    newvalue3 = value3.value.substring(0, 10); 
    apiEndpoint = "man_ana_sql_server/get_MS_LastCt_filter";
  }

  construct_url = `http://10.64.35.32:8000/${apiEndpoint}/?` +
                  `start_time=${start_time}&` +
                  `end_time=${end_time}&` +
                  `point_id=${newvalue3}&` +
                  `page_size=100001`;
  console.log('url',construct_url)
  use_show_data_in_html2();
});

  const maxFieldValMap = new Map();
  const minFieldValMap = new Map();
  const targetCycleMap = new Map();
  const ftqRateMap = new Map();
  const overTargetCountMap = new Map();
  const overCTCountMap = new Map();
  const lessCTCountMap = new Map();
  const conformityRateMap = new Map();  
  const targetSeriesData = ref([]);
  const maxTargetSeriesData = ref([]);
  const minTargetSeriesData = ref([]);
  
  const totalStations = computed(() => tableData.value.length);

const overUpperLimitStations = computed(() => 
  tableData.value.filter(item => item.actual_cycle > (targetCycleMap.get(item.point_id) || 0) * 1.05).length
);

const overLowerLimitStations = computed(() => 
  tableData.value.filter(item => item.actual_cycle < (targetCycleMap.get(item.point_id) || 0) * 0.95).length
);

const conformingStations = computed(() => 
  tableData.value.filter(item => 
    item.actual_cycle >= (targetCycleMap.get(item.point_id) || 0) * 0.95 &&
    item.actual_cycle <= (targetCycleMap.get(item.point_id) || 0) * 1.05
  ).length
);

const stationConformityRate = computed(() => {
  if (totalStations.value === 0) {
    return 0;
  }
  return (conformingStations.value / totalStations.value * 100).toFixed(2);
});

  const fetchTargetCycleData = async () => {
  try {
    const page = value3.value.charAt(10);
    const url = `http://10.64.35.32:8000/as_manage_analysis/get_as_cycle_data/?page=${page}&page_size=1`;
    const response = await axios.get(url);
    const data = response.data;
    const cycleData = data[0].cycle;

    targetCycleMap.clear();

    Object.entries(cycleData).forEach(([pointId, targetCycle]) => {
      targetCycleMap.set(pointId, targetCycle);
    });
  } catch (error) {
    console.error("Failed to fetch target cycle data:", error);
  }
};

const fetchPartCountData = async () => {
  try {
    const start_time = formatDate(value2.value[0]);
  const end_time = formatDate(value2.value[1]);
    const assetnum = value3.value.substring(11, 15);
    const url = `http://10.64.35.32:8000/postgresql_data_api/get_DataPartcount_data/?start_time=${start_time}&end_time=${end_time}&assetnum=${assetnum}&page_size=10000`;
    const response = await axios.get(url);
    const data = response.data;
    ftqRateMap.clear();
    const ftqRateByStation = new Map(); 

    data.forEach(item => {
      const opSuffix = item.assetnum.split('OP')[1]; 
      let goodCount = 0;
      let totalCount = 0;

      if (item.counttype === 'Good') {
        goodCount ++;
      }
      totalCount ++;

      if (ftqRateByStation.has(opSuffix)) {
        const [existingGoodCount, existingTotalCount] = ftqRateByStation.get(opSuffix);
        ftqRateByStation.set(opSuffix, [existingGoodCount + goodCount, existingTotalCount + totalCount]);
      } else {
        ftqRateByStation.set(opSuffix, [goodCount, totalCount]);
      }
    });

    ftqRateByStation.forEach((counts, station) => {
      const [goodCount, totalCount] = counts;
      const ftqRate = totalCount ? goodCount / totalCount : 0;
      ftqRateMap.set(station, ftqRate);
    });
  } catch (error) {
    console.error("Failed to fetch part count data:", error);
  }
};

const fetchDefaultAccumulatedCompensation = async () => {
  try {
    const url = 'http://10.64.35.32:8000/manufacture_analysis/get_ms_cycle_data/?page_size=1000';
    const response = await axios.get(url);
    const data = response.data;
    const defaultCompensationMap = new Map();
    data.forEach(item => {
      defaultCompensationMap.set(item.station, item.equipment_target_time);
    });

    return defaultCompensationMap;
  } catch (error) {
    console.error("Failed to fetch default accumulated compensation data:", error);
    return new Map(); 
  }
};

const use_show_data_in_html2 = async () => {
  await fetchTargetCycleData();
  await fetchPartCountData();
  
  const defaultCompensationMap = await fetchDefaultAccumulatedCompensation();
  const response = await axios.get(construct_url);
  const data = response.data;

  const sumFieldValMap = new Map();
  const countMap = new Map();

  data.forEach(item => {
    const pointId = item.point_id.substring(10, 14);
    const fieldVal = parseFloat(item.field_val);

    if (excludedPoints.includes(pointId)) {
      return;
    }
    if (value3.value === "MPTA0000001ASOP") {
      if (excludedPointsauto.includes(pointId)) {
        return; 
      }
    }
    if (value3.value === "PTA00000001ASOP") {
      if (excludedPointsmanual.includes(pointId)) {
        return; 
      }
    }
   
    if (!sumFieldValMap.has(pointId)) {
      sumFieldValMap.set(pointId, 0);
      countMap.set(pointId, 0);
      maxFieldValMap.set(pointId, fieldVal);
      minFieldValMap.set(pointId, fieldVal);
      overTargetCountMap.set(pointId, 0);
      overCTCountMap.set(pointId, 0);
      lessCTCountMap.set(pointId, 0);
    } else {
      maxFieldValMap.set(pointId, Math.max(maxFieldValMap.get(pointId), fieldVal));
      minFieldValMap.set(pointId, Math.min(minFieldValMap.get(pointId), fieldVal));
    }

    sumFieldValMap.set(pointId, sumFieldValMap.get(pointId) + fieldVal);
    countMap.set(pointId, countMap.get(pointId) + 1);
    overCTCountMap.forEach((overCTCount, key) => {
      const lessCTCount = lessCTCountMap.get(key) || 0;
      const totalCount = countMap.get(key);
      const numerator = overCTCount + lessCTCount;
      const denominator = totalCount;
      const conformityRate = 1 - (numerator / denominator);
      conformityRateMap.set(key, conformityRate);
    });

    const targetCycle = targetCycleMap.get(pointId) || 0;
    if (fieldVal > targetCycle * 10) {
      overTargetCountMap.set(pointId, overTargetCountMap.get(pointId) + 1);
    }
    if (fieldVal > targetCycle * 10.5) {
      overCTCountMap.set(pointId, overCTCountMap.get(pointId) + 1);
    }
    if (fieldVal < targetCycle * 9.5) {
      lessCTCountMap.set(pointId, lessCTCountMap.get(pointId) + 1);
    }
  });
   if (lastPointId) {
      useShowDataInHtmlForTable(lastPointId);
    } else {
      const firstPointId = data[0]?.point_id.substring(10, 14);
      if (firstPointId) {
        lastPointId = firstPointId;
        useShowDataInHtmlForTable(firstPointId);
      }
    }
  const averagedData = Array.from(sumFieldValMap.keys()).map(pointId => {
    const totalFieldVal = sumFieldValMap.get(pointId);
    const count = countMap.get(pointId);
    const avgFieldVal = totalFieldVal / count;
    return { point_id: pointId, field_val: parseFloat((avgFieldVal / 10).toFixed(2)) };
  });

  averagedData.sort((a, b) => {
    const prefixA = a.point_id.substring(0, 3);
    const prefixB = b.point_id.substring(0, 3);
    return prefixA.localeCompare(prefixB);
  });

  series_data1.value = averagedData.map(dataItem => dataItem.point_id);
  series_data.value = averagedData.map(dataItem => dataItem.field_val);
  targetSeriesData.value = averagedData.map(dataItem => {
    const targetCycle = targetCycleMap.get(dataItem.point_id) || 0;
    return targetCycle;
  });
  maxTargetSeriesData.value = targetSeriesData.value.map(targetCycle => targetCycle * 1.05);
  minTargetSeriesData.value = targetSeriesData.value.map(targetCycle => targetCycle * 0.95);
  minTargetSeriesData.value = minTargetSeriesData.value.map(rate => parseFloat(rate.toFixed(2)));
  maxTargetSeriesData.value = maxTargetSeriesData.value.map(rate => parseFloat(rate.toFixed(2)));
  initChart();
  
  let tableDataArray = [];

const savedData = localStorage.getItem(`tableData_${value3.value}`);
if (savedData) {
  const parsedSavedData = JSON.parse(savedData);
  tableDataArray = averagedData.map(dataItem => {
    const existingData = parsedSavedData.find(item => item.point_id === dataItem.point_id);
    if (existingData) {
      return {
        ...existingData,
        actual_cycle: dataItem.field_val + (existingData.accumulated_compensation || 0)
      };
    } else {
      return {
        point_id: dataItem.point_id,
        actual_cycle: dataItem.field_val + (defaultCompensationMap.get(dataItem.point_id) || 0),
        target_cycle: targetSeriesData.value[series_data1.value.indexOf(dataItem.point_id)],
        compensation: 0,
        accumulated_compensation: defaultCompensationMap.get(dataItem.point_id) || 0,
      };
    }
  });
} else {
  tableDataArray = averagedData.map(dataItem => ({
    point_id: dataItem.point_id,
    actual_cycle: dataItem.field_val + (defaultCompensationMap.get(dataItem.point_id) || 0),
    target_cycle: targetSeriesData.value[series_data1.value.indexOf(dataItem.point_id)],
    compensation: 0,
    accumulated_compensation: defaultCompensationMap.get(dataItem.point_id) || 0,
  }));
}

tableData.value = tableDataArray;
saveTableData();
initChart();
};

const tableData = ref([]);

const resetTableData = async () => {
  const storageKey = `tableData_${value3.value}`;
  tableData.value = [];
  localStorage.removeItem(storageKey);
  await use_show_data_in_html2();
};

const applyCompensation = (row) => {  
  const compensation = parseFloat(row.compensation);
  if (!isNaN(compensation)) {
    row.accumulated_compensation += compensation;
    row.actual_cycle += compensation;
    updateChartData(row);
  };

  saveTableData();
  useShowDataInHtmlForTable(row.point_id);
};

const updateChartData = (row) => {
  const index = series_data1.value.findIndex(item => item === row.point_id);
  if (index !== -1) {
    series_data.value[index] = row.actual_cycle;
    initChart();
  }
  saveTableData();
};
const asCycleData = ref(null);


const useShowDataInHtmlForTable = async (point_id) => {
  const start_time = formatDate(value2.value[0]);
  const end_time = formatDate(value2.value[1]);
  lastPointId = point_id;
  let pointIdPart;
  if (value3.value.startsWith('PTA00000') ||value3.value.startsWith('MPTA0000') ||value3.value.startsWith('MPTASCAS01') || value3.value.startsWith('MPTAHCAH01') || value3.value.startsWith('MPTACCAC01')) {
    if (point_id.charAt(0) === '1') {
      pointIdPart = 'MPTASCAS01';
    } else if (point_id.charAt(0) === '2') {
      pointIdPart = 'MPTAHCAH01';
    } else if (point_id.charAt(0) === '3') {
      pointIdPart = 'MPTACCAC01';
    } else {
      pointIdPart = value3.value.substring(0, 10); 
    }
  } else {
    pointIdPart = value3.value.substring(0, 10);
  }

  const page1 = value3.value.charAt(10);

  let apiEndpoint = "man_ana_sql_server/get_MS_LastCt_filter";
  if (pointIdPart.startsWith('MPTASCAS01') || 
      pointIdPart.startsWith('MPTAHCAH01') || 
      pointIdPart.startsWith('MPTACCAC01')) {
    apiEndpoint = "man_ana_sql_server/get_AS_LastCt_filter";
  }

  const newUrl = `http://10.64.35.32:8000/${apiEndpoint}/?` +
                 `start_time=${start_time}&end_time=${end_time}&` +
                 `point_id=${pointIdPart + point_id}&page_size=100001`;
  const tarUrl = `http://10.64.35.32:8000/as_manage_analysis/get_as_cycle_data/?` +
                 `page=${page1}&page_size=1`;

  try {
    const response = await axios.get(newUrl);
    const data = response.data;
    const response1 = await axios.get(tarUrl);
    asCycleData.value = response1.data[0].cycle[point_id];
    tableData1.value = data;
    const targetCycle = asCycleData.value;
    totalItems.value = tableData1.value.length;
    console.log(newUrl)
    
    const correspondingTableItem = tableData.value.find(item => item.point_id === point_id);
    const compensation = correspondingTableItem ? parseFloat(correspondingTableItem.accumulated_compensation) : 0;

    const aggregatedData = aggregateData(data, timeView.value, compensation);

    await initChart2(aggregatedData, point_id, targetCycle);
    fillTableData(data);
    updatePagedData();
  } catch (error) {
    console.error("获取数据时发生错误:", error);
  }
};

const fillTableData = (data) => {
  const sortedData = data.sort((a, b) => new Date(a.timestamp) - new Date(b.timestamp));
  tableData1.value = sortedData.map(item => ({
    时间: item.timestamp,
    节拍: item.field_val /10, 
    工位: item.point_id.substring(10, 14)
  }));
};
const aggregateData = (data, timeView, compensation) => {
  switch (timeView) {
    case 1: 
      return data.map(dataItem => ({
        point_id: dataItem.point_id,
        name: dataItem.timestamp,
        value: (parseFloat(dataItem.field_val) / 10) + compensation
      }));
    case 2: 
      return aggregateByHour(data, compensation);
    case 3: 
      return aggregateByDay(data, compensation);
    default:
      return [];
  }
};

const aggregateByHour = (data, compensation) => {
  const hourlyData = {};
  data.forEach(item => {
    const timestamp = new Date(item.timestamp);
    const month = String(timestamp.getMonth() + 1).padStart(2, '0');
    const day = String(timestamp.getDate()).padStart(2, '0');
    const hour = String(timestamp.getHours()).padStart(2, '0');
    const nextHour = timestamp.getHours() === 23 ? "00" : String(parseInt(hour) + 1).padStart(2, '0');

    const key = `${month}-${day} ${hour}:00-${nextHour}:00`;
    
    if (!hourlyData[key]) {
      hourlyData[key] = {
        sum: 0,
        count: 0
      };
    }
    hourlyData[key].sum += parseFloat(item.field_val);
    hourlyData[key].count++;
  });

  return Object.entries(hourlyData).map(([hour, { sum, count }]) => ({
    name: hour,
    value: ((sum / count / 10) + compensation).toFixed(2)
  }));
};

const aggregateByDay = (data, compensation) => {
  const dailyData = {};

  data.forEach(item => {
    const timestamp = new Date(item.timestamp);
    const key = `${timestamp.getFullYear()}-${String(timestamp.getMonth() + 1).padStart(2, '0')}-${String(timestamp.getDate()).padStart(2, '0')}`;
    if (!dailyData[key]) {
      dailyData[key] = {
        sum: 0,
        count: 0
      };
    }
    dailyData[key].sum += parseFloat(item.field_val);
    dailyData[key].count++;
  });

  return Object.entries(dailyData).map(([day, { sum, count }]) => ({
    name: day,
    value: ((sum / count / 10) + compensation).toFixed(2)
  }));
};
watch(timeView, (newValue) => {
  if (lastPointId) {
    useShowDataInHtmlForTable(lastPointId);
  }
});

const exportToExcel = () => {
  import('xlsx').then(XLSX => {
    const worksheet = XLSX.utils.json_to_sheet(tableData1.value);
    const workbook = { Sheets: { data: worksheet }, SheetNames: ['data'] };
    const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
    const start = formatDate(value2.value[0]);
    const end = formatDate(value2.value[1]);
    const region = value3Label.value.replace(/\s/g, ''); 
    const station = lastPointId; 
    const filename = `${start}_${end}_${region}_${station}_节拍统计.xlsx`;

    saveAs(new Blob([excelBuffer], { type: 'application/octet-stream' }), filename);
  });
};

function handleRowClick(row) {
  if (!compensationValues.value.has(row.point_id)) {
    compensationValues.value.set(row.point_id, 0);
  }
}


</script>

<style scoped>
h3 {
  color: black;
}

.block {
  padding: 20px;
  text-align: center;
  flex: 1;
}
.block:last-child {
  border-right: none;
}
.block .demonstration {
  display: block;
  color: var(--el-text-color-secondary);
  font-size: 14px;
  margin-bottom: 20px;
}
.el-select .el-scrollbar__wrap {
  max-height: 50px !important;
  overflow-y: auto !important;
}

/* 基本样式 */
.el-radio {
  display: flex;
  align-items: center;
}

.el-radio__inner {
  width: 20px;
  height: 20px;
  border-radius: 50%; /* 圆形 */
}

/* 选中状态 */
.el-radio__input.is-checked .el-radio__inner {
  background-color: #409EFF; /* 选中时圆点颜色 */
  border-color: #409EFF; /* 选中时边框颜色 */
}

/* 选中状态的文字颜色 */
.el-radio__label {
  color: #333;
}

.el-radio__input.is-checked + .el-radio__label {
  color: #409EFF; /* 选中时文字颜色 */
}

.summary-table {
  width: 100%;
  border-collapse: collapse;
  border: 1px solid #ddd; /* 添加外边框 */
}

.summary-table th, .summary-table td {
  border: 1px solid #ddd; /* 添加内边框 */
  padding: 8px;
  text-align: center;
}

.summary-table th {
  background-color: #f2f2f2;
}
</style>

